/*
* Part of the CCNx Java Library.
*
* Copyright (C) 2008-2012 Palo Alto Research Center, Inc.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. You should have received
* a copy of the GNU Lesser General Public License along with this library;
* if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
* Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.ccnx.ccn.impl.security.crypto.util;
import java.lang.reflect.Method;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.security.interfaces.DSAKey;
import java.security.interfaces.DSAParams;
import java.security.interfaces.RSAKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.util.Enumeration;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
/**
* Adapted from the CDC Standard Provider's JCA class, this class provides
* the facilities to look up signature algorithm OIDs from digest and encryption
* algorithms, and vice versa.
*
* We start by preloading a lookup table with the standard algorithms, and
* then attempt to screen-scrape any new ones added by providers from
* their property lists.
*
* <ul>
* <li> It attempts to map aliases to standard JCA/JCE names wherever possible,
* and assumes that all Aliases for an engine must map to the same name.
* <li> Two OID mappings with the same OID must map to the same name.
* <li> The <i>Digest</i>with<i>CIpher</i> must be set up as an alias or primary name.
* (i.e. Signature.foo or Alg.Alias.Signature.foo).
* <li> Signature engines that do not have a corresponding cipher engine still require
* a reverse OID mapping of the form Alg.Alias.Cipher.OID.<i>oid</i> = <i>name</i>,
* where <i>name</i> is the cipher name component of the cipher component
* that signature algorithm. This is only a problem for signature algorithms without
* a corresponding cipher component. The most common of these, DSA and ECDSA,
* are handled by default.
* </ul>
*/
public class OIDLookup {
static final boolean debug = true;
/**
* Map from cipher (for ciphers used in signatures; includes DSA) to OID.
**/
private static Map<String,String> _c2oid = new HashMap<String,String>();
/**
* Map from OID to cipher.
**/
private static Map<String,String> _oid2c = new HashMap<String,String>();
/**
* Map from digest to OID.
**/
private static Map<String,String> _d2oid = new HashMap<String,String>();
/**
* Map from OID to digest.
**/
private static Map<String,String> _oid2d = new HashMap<String,String>();
/**
* Map from DigestwithCipher names to OIDs. Only one OID (the preferred one)
* for a DigestwithCipher.
**/
private static Map<String,String> _s2oid = new HashMap<String,String>();
/**
* Map from OID to DigestwithCipher names. Multiway -- all known OIDs listed.
**/
private static Map<String,String> _oid2s = new HashMap<String,String>();
/**
* Map from OID to Mac algorithm names. Multiway -- all known OIDs listed.
**/
private static Map<String,String> _oid2m = new HashMap<String,String>();
/**
* Map from Mac algorithm names to OIDs. Only one OID (the preferred one)
* for a DigestwithCipher.
**/
private static Map<String,String> _m2oid = new HashMap<String,String>();
/**
* Map from engine type to OID maps.
**/
private static Map<String,Map<String,String>> _e2oid2alg = new HashMap<String, Map<String,String>>();
/**
* Map that goes the other way.
**/
private static Map<String,Map<String,String>> _e2alg2oid = new HashMap<String,Map<String,String>>();
/**
* Map from provider name to provider alias map.
**/
protected static Map<String,Map<String,String>> _aliasMap;
/**
* Preload the maps.
**/
static {
_e2oid2alg.put("Signature", _oid2s);
_e2oid2alg.put("Cipher", _oid2c);
_e2oid2alg.put("MessageDigest", _oid2d);
_e2oid2alg.put("Mac", _oid2m);
_e2alg2oid.put("Signature", _s2oid);
_e2alg2oid.put("MessageDigest", _d2oid);
_e2alg2oid.put("Cipher", _c2oid);
_e2alg2oid.put("Mac", _m2oid);
_s2oid.put("SHA1withRSA", "1.2.840.113549.1.1.5");
_oid2s.put("1.2.840.113549.1.1.5", "SHA1withRSA");
_oid2s.put("1.3.14.3.2.29", "SHA1withRSA");
_s2oid.put("SHAwithRSA", "1.2.840.113549.1.1.5");
_s2oid.put("SHA-1withRSA", "1.2.840.113549.1.1.5");
_s2oid.put("SHA256withRSA", "1.2.840.113549.1.1.11");
_oid2s.put("1.2.840.113549.1.1.11", "SHA256withRSA");
_s2oid.put("SHA-256withRSA", "1.2.840.113549.1.1.11");
_s2oid.put("SHA384withRSA", "1.2.840.113549.1.1.12");
_oid2s.put("1.2.840.113549.1.1.12", "SHA384withRSA");
_s2oid.put("SHA-384withRSA", "1.2.840.113549.1.1.12");
_s2oid.put("SHA512withRSA", "1.2.840.113549.1.1.13");
_oid2s.put("1.2.840.113549.1.1.13", "SHA512withRSA");
_s2oid.put("SHA-512withRSA", "1.2.840.113549.1.1.13");
_s2oid.put("MD5withRSA", "1.2.840.113549.1.1.4");
_oid2s.put("1.2.840.113549.1.1.4", "MD5withRSA");
_oid2s.put("1.3.14.3.2.25", "MD5withRSA");
_s2oid.put("RipeMD160withRSA", "1.3.36.3.3.1.2");
_s2oid.put("RIPEMD160withRSA", "1.3.36.3.3.1.2");
_oid2s.put("1.3.36.3.3.2.1", "RIPEMD160withRSA");
_s2oid.put("SHA1withDSA", "1.2.840.10040.4.3");
_oid2s.put("1.3.14.3.2.13", "SHA1withDSA");
_oid2s.put("1.2.840.10040.4.3", "SHA1withDSA");
_oid2s.put("1.3.14.3.2.27", "SHA1withDSA");
_s2oid.put("SHAwithDSA", "1.2.840.10040.4.3");
_s2oid.put("SHA-1withDSA", "1.2.840.10040.4.3");
_s2oid.put("SHA1withECDSA", "1.2.840.10045.4.1");
_oid2s.put("1.2.840.10045.4.1", "SHA1withECDSA");
_s2oid.put("SHA224withECDSA", "1.2.840.10045.4.3.1");
_s2oid.put("SHA-224withECDSA", "1.2.840.10045.4.3.1");
_oid2s.put("1.2.840.10045.4.3.1", "SHA224withECDSA");
_s2oid.put("SHA256withECDSA", "1.2.840.10045.4.3.2");
_s2oid.put("SHA-256withECDSA", "1.2.840.10045.4.3.2");
_oid2s.put("1.2.840.10045.4.3.2", "SHA256withECDSA");
_s2oid.put("SHA384withECDSA", "1.2.840.10045.4.3.3");
_s2oid.put("SHA-384withECDSA", "1.2.840.10045.4.3.3");
_oid2s.put("1.2.840.10045.4.3.3", "SHA384withECDSA");
_s2oid.put("SHA512withECDSA", "1.2.840.10045.4.3.4");
_s2oid.put("SHA-512withECDSA", "1.2.840.10045.4.3.4");
_oid2s.put("1.2.840.10045.4.3.4", "SHA512withECDSA");
_d2oid.put("SHA1", "1.3.14.3.2.26");
_d2oid.put("SHA-1", "1.3.14.3.2.26");
_d2oid.put("SHA", "1.3.14.3.2.26");
_oid2d.put("1.3.14.3.2.26", "SHA1");
_d2oid.put("SHA256", "2.16.840.1.101.3.4.2.1");
_d2oid.put("SHA-256", "2.16.840.1.101.3.4.2.1");
_oid2d.put("2.16.840.1.101.3.4.2.1", "SHA256");
_d2oid.put("SHA384", "2.16.840.1.101.3.4.2.2");
_d2oid.put("SHA-384", "2.16.840.1.101.3.4.2.2");
_oid2d.put("2.16.840.1.101.3.4.2.2", "SHA384");
_d2oid.put("SHA512", "2.16.840.1.101.3.4.2.3");
_d2oid.put("SHA-512", "2.16.840.1.101.3.4.2.3");
_oid2d.put("2.16.840.1.101.3.4.2.3", "SHA512");
_d2oid.put("MD4", "1.2.840.113549.2.4");
_oid2d.put("1.2.840.113549.2.4", "MD4");
_d2oid.put("MD5", "1.2.840.113549.2.5");
_oid2d.put("1.2.840.113549.2.5", "MD5");
_d2oid.put("RIPEMD160", "1.3.36.3.2.1");
_d2oid.put("RipeMD160", "1.3.36.3.2.1");
_oid2d.put("1.3.36.3.2.1", "RIPEMD160");
_d2oid.put("RIPEMD128", "1.3.36.3.2.2");
_d2oid.put("RipeMD128", "1.3.36.3.2.2");
_oid2d.put("1.3.36.3.2.2", "RIPEMD128");
_d2oid.put("SHA1MHT", "1.2.840.113550.11.1.2.1");
_d2oid.put("SHA-1MHT", "1.2.840.113550.11.1.2.1");
_oid2d.put("1.2.840.113550.11.1.2.1", "SHA1MHT");
_d2oid.put("SHA256MHT", "1.2.840.113550.11.1.2.2");
_d2oid.put("SHA-256MHT", "1.2.840.113550.11.1.2.2");
_oid2d.put("1.2.840.113550.11.1.2.2", "SHA256MHT");
_c2oid.put("RSA", "1.2.840.113549.1.1.1");
_oid2c.put("1.2.840.113549.1.1.1", "RSA");
_c2oid.put("DSA", "1.2.840.10040.4.1");
_oid2c.put("1.2.840.10040.4.1", "DSA");
_oid2c.put("1.3.14.3.2.12", "DSA");
_c2oid.put("ECDSA", "1.2.840.10045.2.1");
_c2oid.put("EC", "1.2.840.10045.2.1"); // PrivateKey.getAlgorithm()
_oid2c.put("1.2.840.10045.2.1", "ECDSA");
_c2oid.put("ElGamal", "1.3.14.7.2.1.1");
_oid2c.put("1.3.14.7.2.1.1", "ElGamal");
_c2oid.put("DH", "1.2.840.113549.1.3.1");
_oid2c.put("1.2.840.113549.1.3.1", "DH");
_oid2c.put("1.2.840.10046.2.1", "DH"); // ANSI 942, used by BouncyCastle
_m2oid.put("HMac-SHA256", "1.2.840.112549.2.9");
_m2oid.put("HMACSHA256", "1.2.840.112549.2.9");
_m2oid.put("HMAC-SHA256", "1.2.840.112549.2.9");
_d2oid.put("HMac-SHA256", "2.16.840.1.101.3.4.2.1");
_d2oid.put("HMACSHA256", "2.16.840.1.101.3.4.2.1");
_d2oid.put("HMAC-SHA256", "2.16.840.1.101.3.4.2.1");
_oid2m.put("1.2.840.112549.2.9", "HMac-SHA256");
_aliasMap = initAliasLookup();
}
/**
* Map from a digest algorithm name and a cipher algorithm name to an OID.
* @param digestAlg the digest algorithm.
* @param cipherAlg the cipher algorithm.
* @return the OID
*/
public static String getSignatureAlgorithmOID(String digestAlg, String cipherAlg) {
digestAlg = resolveDigestAlias(digestAlg);
cipherAlg = resolveCipherAlias(cipherAlg);
StringBuffer signatureAlgorithm = new StringBuffer(digestAlg);
signatureAlgorithm.append("with");
signatureAlgorithm.append(cipherAlg);
String oid = mapGet(_s2oid, signatureAlgorithm.toString());
return oid; // might be null
}
/**
* Map from a digest algorithm name and a cipher algorithm to a signature algorithm
* name. If the signature algorithm name doesn't exist, return null.
* @param digestAlg the digest algorithm.
* @param cipherAlg the cipher algorithm.
* @return the signature algorithm.
*/
public static String getSignatureAlgorithm(String digestAlg, String cipherAlg) {
String resolvedCipherAlg = resolveCipherAlias(cipherAlg);
if (null == resolvedCipherAlg)
return resolveMacAlias(cipherAlg);
digestAlg = resolveDigestAlias(digestAlg);
StringBuffer signatureAlgorithm = new StringBuffer(digestAlg);
signatureAlgorithm.append("with");
signatureAlgorithm.append(resolvedCipherAlg);
String sigAlg = signatureAlgorithm.toString();
String oid = mapGet(_s2oid, sigAlg.toString());
if (oid != null) {
return sigAlg;
}
return null;
}
/**
* Map from a signature algorithm to a cipher.
* @param signatureAlgorithm the signature algorithm.
* @return the cipher.
*/
public static String signatureAlgorithmToCipher(String signatureAlgorithm) {
signatureAlgorithm = resolveSignatureAlias(signatureAlgorithm);
String [] dac = signatureAlgorithmToDigestAndCipher(signatureAlgorithm);
return dac[1];
}
/**
* Map from a signature algorithm to a digest.
* @param signatureAlgorithm the signature algorithm.
* @return the digest.
*/
public static String signatureAlgorithmToDigest(String signatureAlgorithm) {
signatureAlgorithm = resolveSignatureAlias(signatureAlgorithm);
String [] dac = signatureAlgorithmToDigestAndCipher(signatureAlgorithm);
return dac[0];
}
/**
* Get the OID for a cipher algorithm.
* This only works for ciphers used in signatures.
* @param cipherAlgorithm the cipher algorithm.
* @return the OID.
*/
public static String getCipherOID(String cipherAlgorithm) {
cipherAlgorithm = resolveCipherAlias(cipherAlgorithm);
return mapGet(_c2oid, cipherAlgorithm);
}
/**
* Return the preferred OID for a digest algorithm.
* @param digestAlgorithm the digest algorithm.
* @return the OID.
*/
public static String getDigestOID(String digestAlgorithm) {
digestAlgorithm = resolveDigestAlias(digestAlgorithm);
return mapGet(_d2oid, digestAlgorithm);
}
/**
* Return the preferred OID for a signature algorithm.
**/
public static String getSignatureOID(String algorithm) {
algorithm = resolveSignatureAlias(algorithm);
return mapGet(_s2oid, algorithm);
}
/**
* Return the preferred OID for a MAC algorithm
*/
public static String getMacOID(String algorithm) {
algorithm = resolveMacAlias(algorithm);
return mapGet(_m2oid, algorithm);
}
/**
* Return the preferred name for a signature OID.
**/
public static String getSignatureName(String oid) {
return mapGet(_oid2s, oid);
}
/**
* Return the preferred name for a digest OID.
**/
public static String getDigestName(String oid) {
return mapGet(_oid2d, oid);
}
/**
* Return the preferred name for a cipher OID.
**/
public static String getCipherName(String oid) {
return mapGet(_oid2c, oid);
}
/**
* Parse a DigestwithCipher name into its digest and cipher components.
* Attempt to cope with aliases, etc.
**/
public static String[] signatureAlgorithmToDigestAndCipher(String signatureAlgorithm) {
signatureAlgorithm = resolveSignatureAlias(signatureAlgorithm);
if (signatureAlgorithm == null) {
return new String[]{null, null};
}
// Should be a splittable string.
String [] dandc = signatureAlgorithm.split("with");
if (dandc.length != 2) {
// We have a problem.
String [] dandctry2 = signatureAlgorithm.split("/");
if (dandctry2.length != 2) {
System.out.println("System error: splitting canonical signature algorithm name: " +
signatureAlgorithm +
" failed. Not of the form DigestwithCipher or Digest/Cipher.");
} else {
dandc = dandctry2;
}
}
return dandc;
}
/*
static private void dump(Map map)
{
Iterator i;
Map.Entry entry;
for (i=map.entrySet().iterator(); i.hasNext();)
{
entry = (Map.Entry)i.next();
System.out.println(
entry.getKey()+" = "+entry.getValue());
}
}
*/
/**
* This method maps a given digest algorithm OID and
* cipher algorithm OID onto the standard name of the
* combined signature algorithm. For this to work the
* aliases must be well defined such as described below:
* <dl>
* <dt> Digest Algorithm
* <dd> Alg.Alias.MessageDigest.<i>oid</i><sub>1</sub>
* = <i>digestAlg</i>
* <dt> Cipher Algorithm
* <dd> Alg.Alias.Cipher.<i>oid</i><sub>2</sub>
* = <i>cipherAlg</i>
* <dt> Signature Algorithm
* <dd> Alg.Alias.Signature.<i>digestAlg</i>/<i>cipherAlg</i>
* = <i>signatureAlg</i>
* </dl>
* The <i>oid</i> denotes the sequence of OID numbers
* separated by dots but without a leading "OID.".
* In some cases, such as the DSA, there is no cipher engine
* corresponding to <i>oid</i><sub>2</sub>. In this case,
* <i>oid</i><sub>2</sub> must be mapped to the corresponding
* name by other engine types, such as a KeyFactory.<p>
*
* All found mappings are cached for future use, as well
* as the reverse mapping, which is much more complicated
* to synthesise.
*
* @param doid The string representation of the digest
* algorithm OID. The OID must have a "OID."
* prefix.
* @param coid The string representation of the cipher
* algorithm OID. The OID must have a "OID."
* prefix.
* @return The standard JCE name of the signature algorithm
* or <code>null</code> if no mapping could be found.
*/
public static String getSignatureAlgorithmFromOIDs(String doid, String coid) {
String dn;
String cn;
dn = getDigestName(doid);
cn = getCipherName(coid);
if (dn == null || cn == null)
return null;
return getSignatureAlgorithm(dn, cn);
}
/**
* Reads the properties of the installed providers and
* builds an optimized alias lookup table. All entries
* of the form
* <ol>
* <li> "Alg.Alias."+<engine>+"."+<alias>
* = <value>
* <li> "Alg.Alias."+<engine>+".OID."+<oid>
* = <value>
* <li> "Alg.Alias."+<engine>+"."+<oid>
* = <value>
* </ol>
* are transformed and stored in a hashmap which is used
* by this class in order to do quick lookups of aliases
* and OID mappings. The stored entries are of the form:
* <ol>
* <li> <engine>+"."+<alias>
* = <value>
* <li> "oid."+<value>
* = <oid>
* <li> "oid."+<oid>
* = <value>
* </ol>
* In case multiple providers define mappings for the same
* keys the mapping of the first registered provider wins.
*/
static private Map<String,Map<String,String>> initAliasLookup() {
Enumeration<?> e;
Provider[] providers;
String k; // key
String v; // value
String s; // string
String p; // previous mapping
Map<String,Map<String,String>> map;
int i;
int j;
map = new HashMap<String,Map<String,String>>();
providers = Security.getProviders();
Map<String,String> submap = null; // keep our aliases separate.
/* We start from the last provider and work our
* way to the first one such that aliases of
* preferred providers overwrite entries of
* less favored providers.
*/
for (i=providers.length-1; i>=0; i--) {
e = providers[i].propertyNames();
while (e.hasMoreElements()) {
k = (String)e.nextElement();
v = providers[i].getProperty(k);
if (!k.startsWith("Alg.Alias."))
continue;
// Truncate k to <engine>.<alias>
k = k.substring(10).toLowerCase();
j = k.indexOf('.');
if (j<1)
continue;
/* Copy <engine> to s
* Truncate k to <alias>
*/
s = k.substring(0,j);
k = k.substring(j+1);
if (k.length() < 1)
continue;
/* Get the engine alias map and the engine-oid maps. */
submap = map.get(s);
if (null == submap) {
submap = new HashMap<String,String>();
map.put(s, submap);
}
/* If <alias> starts with a digit, then we
* assume it is an OID. OIDs are uniquely
* defined, hence we omit <engine> in the
* oid mappings. But we also include the
* alias mapping for this oid.
*/
if (Character.isDigit(k.charAt(0))) {
p = submap.get(k);
if (p != null && p.length() >= v.length())
continue;
submap.put(k,v);
// should we check to see if we have this one already? Should we add it to main
// maps?
Map<String,String> oidmap = _e2oid2alg.get(s);
Map<String,String> algmap = _e2alg2oid.get(s);
if ((null != oidmap) && (null != algmap)) {
if (!oidmap.containsKey(k)) {
oidmap.put(k, v);
if (!algmap.containsKey(v)) {
algmap.put(v, k);
}
}
}
} else if (k.startsWith("oid.")) {
/* If <alias> starts with the string "OID."
* then we found a reverse mapping. In that
* case we swap <alias> and the value of the
* mapping, and make an entry of the form
* "oid."+<value> = <oid>
*/
k = k.substring(4);
v = v.toLowerCase();
Map<String,String> oidmap = _e2oid2alg.get(s);
Map<String,String> algmap = _e2alg2oid.get(s);
if ((null != oidmap) && (null != algmap)) {
if (!oidmap.containsKey(k)) {
oidmap.put(k, v);
if (!algmap.containsKey(v)) {
algmap.put(v, k);
}
}
}
} else {
/* In all other cases we make an entry of the
* form <engine>+"."+<alias> = <value> as is
* defined in the providers.
*/
submap.put(k, v);
}
}
}
return map;
}
/**
* For specific types, attempts to see if the current name passed in is the
* canonical name. If not passes problem to resolveAlias.
**/
public static String resolveCipherAlias(String alias) {
return resolveAlias("Cipher", alias);
}
public static String resolveDigestAlias(String alias) {
return resolveAlias("MessageDigest", alias);
}
public static String resolveMacAlias(String alias) {
return resolveAlias("Mac", alias);
}
public static String resolveSignatureAlias(String alias) {
return resolveAlias("Signature", alias);
}
/*
* AES OIDs depend on key length.
*/
/* public static String getAESOID(String algorithm, int keyLength) {
}
public static String aesOIDToAlgorithm(String oid) {
}
public static int aesOIDToKeyLength(String oid) {
}
*/
/**
* Resolves the given alias to the standard JCA name for the
* given engine type. If no appropriate mapping is defined
* then <code>null</code> is returned. If the given alias is
* actually an OID string and there is an appropriate alias
* mapping defined for that OID by some provider then the
* corresponding JCA name is returned.
*
* @param engine The JCA engine type name.
* @param alias The alias to resolve for the given engine type.
* @return The standard JCA name or <code>null</code> if no
* appropriate mapping could be found.
*/
public static String resolveAlias(String engine, String alias) {
if (alias == null || engine == null)
throw new NullPointerException("Engine or alias is null!");
if (alias.length() < 1)
throw new IllegalArgumentException("Zero-length alias!");
Map<String,String> oid2alg = mapGet(_e2oid2alg, engine);
Map<String,String> alg2oid = mapGet(_e2alg2oid, engine);
if ((null != oid2alg) && (null != alg2oid)) {
if (Character.isDigit(alias.charAt(0))) {
// oid
if (mapContainsKey(oid2alg, alias)) {
return mapGet(oid2alg, alias);
}
} else {
if (mapContainsKey(alg2oid, alias)) {
return reverseLookup(alg2oid, oid2alg, alias);
}
}
}
Map<String,String> engineMap = _aliasMap.get(engine);
if (null != engineMap) {
alias = mapGet(engineMap, alias.toLowerCase());
if ((null != alias) && (null != oid2alg) && (null != alg2oid)) {
if (Character.isDigit(alias.charAt(0))) {
// oid
if (mapContainsKey(oid2alg, alias)) {
return mapGet(oid2alg, alias);
}
} else {
if (mapContainsKey(alg2oid, alias)) {
return reverseLookup(alg2oid, oid2alg, alias);
}
}
}
}
return null;
}
/**
* Map accessors that handle synchronization.
* TODO replace with read-only maps, and make these go away after
* initialization. (Can also use Collection.synchronizedMap).
**/
public static boolean mapContainsKey(Map<?,?> map, Object key) {
synchronized(map) {
return map.containsKey(key);
}
}
public static <T1,T2> T2 mapGet(Map<T1,T2> map, T1 key) {
synchronized(map) {
return map.get(key);
}
}
public static <T1,T2> void mapPut(Map<T1,T2> map, T1 key, T2 value) {
synchronized(map) {
if (!map.containsKey(key))
map.put(key, value);
}
}
public static String reverseLookup(Map<String,String> e2oid, Map<String,String> oid2e, String alias) {
String oid = mapGet(e2oid, alias);
// Shouldn't be null
if (null == oid) {
return oid;
}
return mapGet(oid2e, oid);
}
/**
* Unfortunately, there's no easy way to do this.
* Need to add a way to get parameters from each new key type. Makes it hard to add
* new key types dynamically. The parameter interfaces should be cleaned up in Java.
* So instead, we try reflection...
**/
public static AlgorithmParameters getParametersFromKey(Key key)
throws NoSuchAlgorithmException, InvalidParameterSpecException {
AlgorithmParameters algParams = null;
// Handle the obvious cases, try to get a little general with reflection.
if (key instanceof RSAKey) {
// do nothing, params should be null (as opposed to RSAKeyGenerator parameters,
// which actually do contain stuff). Don't use those here.
} if (key instanceof DSAKey) {
DSAParams params = ((DSAKey)key).getParams();
algParams = AlgorithmParameters.getInstance("DSA");
// the only class implementing DSAParams is DSAParameterSpec
algParams.init((AlgorithmParameterSpec)params);
} else {
// Let's see if we can find a method called getParams or getParameters that
// returns something that can be coerced into an AlgorithmParameters or an AlgorithmParametersSpec.
Method [] methods = key.getClass().getDeclaredMethods();
// Try them in order that we get them.
for (int i=0; i < methods.length; ++i) {
if ((methods[i].getName().equalsIgnoreCase("getParams")) ||
(methods[i].getName().equalsIgnoreCase("getParameters"))) {
if (AlgorithmParameters.class.isAssignableFrom(methods[i].getReturnType())) {
// Pass in null for any arguments.
Object [] args = new Object[methods[i].getParameterTypes().length];
try {
algParams = (AlgorithmParameters)methods[i].invoke(key, args);
if (null != algParams) {
break; // we're done}
}
} catch (Exception ex) {
// Go around again
if (debug) {
System.out.println("Tried invoking method: " + methods[i].getName() + " on object of type: " +
key.getClass().getName() + ", got exception: " +
ex.getClass().getName() + " message: " + ex.getMessage());
}
continue;
}
} else if (AlgorithmParameterSpec.class.isAssignableFrom(methods[i].getReturnType())) {
// Pass in null for any arguments.
Object [] args = new Object[methods[i].getParameterTypes().length];
try {
AlgorithmParameterSpec spec = (AlgorithmParameterSpec)methods[i].invoke(key, args);
if (null == spec) {
continue;
}
algParams = AlgorithmParameters.getInstance(key.getAlgorithm());
if (algParams != null) {
algParams.init(spec);
if (algParams != null) {
break;
}
}
} catch (Exception ex) {
// Go around again
if (debug) {
System.out.println("Tried invoking method: " + methods[i].getName() + " on object of type: " +
key.getClass().getName() + ", got exception: " +
ex.getClass().getName() + " message: " + ex.getMessage());
}
continue;
}
}
}
}
}
return algParams;
}
public static AlgorithmParameters getParamsFromKey(RSAKey rsakey) {
// don't want the generation parameters, want the null
return null;
}
/**
* Prints the list of loaded providers.
*/
public static void listLoadedProviders() {
Set<String> providers = _aliasMap.keySet();
for (String s : providers) {
System.out.println("OIDLookup: loaded provider " + s);
}
}
/**
* Prints the list of loaded aliases.
*/
public static void listLoadedAliases() {
Set<String> providers = _aliasMap.keySet();
for (String p : providers) {
Map<String,String> aliases = _aliasMap.get(p);
System.out.println("Dumping aliases for provider: " + p);
for (String a : aliases.keySet()) {
System.out.println(" " + a + ": " + aliases.get(a));
}
}
}
/**
* Static use only.
**/
private OIDLookup() {}
}